import numpy as np
import pandas as pd
import plotly.express as px
import matplotlib.pyplot as plt
from scipy.optimize import fsolve
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from scipy.optimize import minimize
df = pd.read_excel("market_data_2023 (1).xlsx", sheet_name=0)
df = df[0:11]
df = df.drop(['Date'], axis=1)
df.columns = df.iloc[0]
df = df[1:]
df.reset_index(drop=True, inplace=True)
df.rename(columns={df.columns[0]: 'Maturity'}, inplace=True)
df
| Maturity | Banco Santander | Eni | Ziggo | Lufthansa | Renault | Allianz | |
|---|---|---|---|---|---|---|---|
| 0 | 0.5 | 24130 | 19570 | 93560 | 93000 | 73160 | 14840 |
| 1 | 1.0 | 30280 | 26840 | 134260 | 119940 | 83130 | 20110 |
| 2 | 2.0 | 40800 | 39600 | 208920 | 139830 | 150590 | 27430 |
| 3 | 3.0 | 51230 | 52190 | 292940 | 159550 | 215880 | 34670 |
| 4 | 4.0 | 61900 | 65310 | 372710 | 198290 | 273440 | 41520 |
| 5 | 5.0 | 72590 | 78210 | 446770 | 236070 | 327820 | 48290 |
| 6 | 7.0 | 85030 | 100980 | 527180 | 269500 | 395740 | 58350 |
| 7 | 10.0 | 95670 | 122460 | 574230 | 291570 | 413030 | 68860 |
| 8 | 20.0 | 106920 | 144560 | 612050 | 313450 | 430260 | 80010 |
| 9 | 30.0 | 115570 | 160360 | 621800 | 325460 | 436880 | 88960 |
fig = go.Figure()
for column in df.columns[1:]:
fig.add_trace(
go.Scatter(
x=df['Maturity'],
y=df[column],
mode='lines+markers',
name=column,
marker=dict(size=6),
line=dict(width=1),
line_shape='linear'
)
)
# Update layout
fig.update_layout(
title="Cds spread",
xaxis_title="Maturity",
yaxis_title="CDS spread",
font=dict(family="Times New Roman", size=10, color="Black"),
template="plotly_white",
showlegend=True,
yaxis=dict(range=[0, 700000])
)
fig.show()
def lambdas_and_gammas(maturities, delta, zcb, spread, LGD):
n = len(maturities)
lambdas = np.zeros(n)
gammas = np.zeros(n)
def objective_function(hazard_rate, i):
cumulative_intensity = sum(lambdas[:i] * delta[:i])
protection_leg = LGD * sum(
hazard_rate * zcb[j] * np.exp(-(cumulative_intensity))
for j in range(i+1)
)
premium_leg = sum(
spread[j] * zcb[j] * delta[j] * np.exp(-(cumulative_intensity))
for j in range(i+1)
)
return (protection_leg - premium_leg) ** 2
for i in range(n):
result = minimize(
objective_function,
x0=np.array([spread[i] * delta[i] / LGD]),
args=(i,),
bounds=[(0, 3)]
)
lambdas[i] = result.x[0]
gammas[i] = sum(lambdas[:i+1] * delta[:i+1])
return lambdas, gammas
def survival_default(df, maturities, delta, zcb, firm_names, LGD):
all_survival_probs = []
all_default_probs = []
all_hazard_rates = []
for firm_name in firm_names:
spread = df[firm_name] / 10000000
lambdas, gammas = lambdas_and_gammas(maturities, delta, zcb, spread, LGD)
survival_prob = [np.exp(-gamma) for gamma in gammas]
default_prob = [1 - sp for sp in survival_prob]
all_survival_probs.append(survival_prob)
all_default_probs.append(default_prob)
all_hazard_rates.append(lambdas)
return all_survival_probs, all_default_probs, all_hazard_rates
def plot_results_with_plotly(df, maturities, delta, zcb, firm_names, LGD):
all_survival_probs, all_default_probs, all_hazard_rates = survival_default(df, maturities, delta, zcb, firm_names, LGD)
fig_survival = go.Figure()
for i, firm_name in enumerate(firm_names):
fig_survival.add_trace(go.Scatter(x=maturities, y=all_survival_probs[i], mode='lines+markers',
name=f"{firm_name}", marker=dict(size=6),
line=dict(width=1), line_dash='dash'))
fig_survival.update_layout(
title="Survival Probability",
xaxis_title="Maturity",
yaxis_title="Survival Probability",
font=dict(family="Times New Roman", size=10, color="Black"),
template="plotly_white",
showlegend=True
)
fig_survival.show()
# Plot Default Probabilities
fig_default = go.Figure()
for i, firm_name in enumerate(firm_names):
fig_default.add_trace(go.Scatter(x=maturities, y=all_default_probs[i], mode='lines+markers',
name=f"{firm_name}", marker=dict(size=6),
line=dict(width=1), line_dash='dash'))
fig_default.update_layout(
title="Default Probability",
xaxis_title="Maturity ",
yaxis_title="Default Probability",
font=dict(family="Times New Roman", size=10, color="Black"),
template="plotly_white",
showlegend=True
)
fig_default.show()
# Plot Hazard Rates
fig_hazard = go.Figure()
for i, firm_name in enumerate(firm_names):
fig_hazard.add_trace(go.Scatter(x=maturities, y=all_hazard_rates[i], mode='lines+markers',
name=f"{firm_name}", marker=dict(size=6),
line=dict(width=1), line_shape='linear'))
fig_hazard.update_layout(
title="Hazard Rates ",
xaxis_title="Maturity",
yaxis_title="Hazard Rate",
font=dict(family="Times New Roman", size=10, color="Black"),
template="plotly_white",
showlegend=True
)
fig_hazard.show()
# Create the figure
fig_hazard = go.Figure()
# Add step-line traces for all firms
for i, firm_name in enumerate(firm_names):
fig_hazard.add_trace(
go.Scatter(
x=maturities,
y=all_hazard_rates[i],
mode='lines',
name=f"{firm_name}",
line=dict(shape='hv', width=2), # Use step-line style (hv)
marker=dict(size=6)
)
)
# Update layout
fig_hazard.update_layout(
title="Hazard Rates",
xaxis_title="Maturity",
yaxis_title="Hazard Rate",
font=dict(family="Times New Roman", size=10, color="Black"),
template="plotly_white",
showlegend=True
)
# Show the figure
fig_hazard.show()
zcb = pd.read_csv('ZCB_prices.csv')
zcb_filtered = zcb[zcb['Maturity'].isin(df['Maturity'])]
zcb_filtered = zcb['ZCB_price']
maturities = df.Maturity
delta = [0.5, 0.5, 1.0, 1.0, 1.0, 1.0, 2.0, 3.0,10.0, 10.0]
zcb = zcb_filtered
R = 0.4
LGD = 1 - R
firm_names = df.columns[1:]
plot_results_with_plotly(df, maturities, delta, zcb, firm_names, LGD)